package main

import (
	"bytes"
	"gitee.com/stlswm/ConfigAdapter/JsonConfig"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"sync"
)

func main() {
	// 当前目录
	var dir string
	var err error
	if len(os.Args) >= 2 && os.Args[1] != "" {
		dir = os.Args[1]
	} else {
		dir, err = filepath.Abs(filepath.Dir(os.Args[0]))
		log.Println(os.Args)
		if err != nil {
			panic(err)
		}
	}
	log.Printf("配置文件加载目录：%s", dir)
	// 配置解析
	var config struct {
		ReqNum int
		Url    string
		Header map[string]string
		Body   string
	}
	err = JsonConfig.Load(dir+"/config.json", &config)
	if err != nil {
		panic(err)
	}
	var times = config.ReqNum
	taskChan := make(chan int, times)
	var wg sync.WaitGroup
	for i := 0; i < times; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			res := post(config.Url, config.Header, []byte(config.Body))
			if res != nil {
				taskChan <- res.StatusCode
			} else {
				taskChan <- 0
			}
		}()
	}
	// 使用WaitGroup等待所有goroutine完成
	wg.Wait()
	// 收集所有完成信号
	httpStatusStatistics := make(map[int]int)
	httpStatusRateStatistics := make(map[int]float64)
	successTimes := 0
	for i := 1; i <= times; i++ {
		httpCode := <-taskChan // 从done channel接收完成信号
		httpStatusStatistics[httpCode] += 1
		httpStatusRateStatistics[httpCode] = float64(httpStatusStatistics[httpCode]) / float64(times) * 100.0
		if httpCode == 200 {
			successTimes++
		}
	}
	log.Printf("总请求数：%d，请求成功响应率： %.4f %%, 成功响应次数：%d", times, float64(successTimes)/float64(times)*100.0, successTimes)
	for status, num := range httpStatusStatistics {
		rate := httpStatusRateStatistics[status]
		log.Printf("状态码： %d, 次数：%d，占比：%.4f %%", status, num, rate)
	}
}

func post(url string, header map[string]string, body []byte) *http.Response {
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
	if err != nil {
		log.Fatalf("Error creating request: %v", err)
	}
	// 设置请求头
	for key, value := range header {
		req.Header.Set(key, value)
	}
	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("Error sending request: %v", err)
		return nil
	}
	defer resp.Body.Close()
	return resp
}
